package com.ht.api.call.func.impl.kf;

import javax.sql.DataSource;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import com.ht.api.bean.AjaxResult;
import com.ht.api.bean.LoginBean;
import com.ht.api.call.func.IFunctionCall;
import com.ht.api.constant.KfSessionStatus;
import com.ht.api.constant.Message;
import com.ht.api.db.Db;
import com.ht.api.db.DbList;
import com.ht.api.db.Entity;
import com.ht.api.db.exception.HtException;
import com.ht.api.service.ExternalContactService;
import com.ht.api.websocket.WebSocket;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 开始会话
 * @author asq
 * @createTime 2025年3月17日 10:41:36
 */
@Slf4j
public class KfSessionStartFunctionCall implements IFunctionCall {
	/** 锁 */
	private RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class);
    
    private WebSocket webSocket;

	@Override
	public String getName() {
		return "开始会话";
	}

	@Override
	public JSONObject execute(LoginBean me, JSONObject param, AjaxResult result) {
		// 获取登陆用户的数据源
		DataSource ds = me.getDataSource();
		
		// 获取会话
		String sessionId = param.getStr("main_id");
		Entity kfSession = Db.createSqlParser("kf_session").findById(ds, sessionId);
		if (kfSession == null) {
			throw new HtException("会话main_id不存在：" + sessionId);
		}
		if (KfSessionStatus.PROGRESS == kfSession.getInt("status")) {
			throw new HtException("会话正在接待中，不能再次接待~");
		}
		if (KfSessionStatus.OVER == kfSession.getInt("status")) {
			throw new HtException("会话已结束，不能接待~");
		}
		
		// 加锁
		RLock lock = redissonClient.getLock(sessionId);
		if (lock.tryLock()) {
			try {
				// 开始会话
				Entity kfSessionUpdate = Db.createEntity("kf_session");
				kfSessionUpdate.setMainId(sessionId);
				kfSessionUpdate.set("status", KfSessionStatus.PROGRESS);
				kfSessionUpdate.set("userid", me.getLoginIdStr());
				Db.insert(ds, kfSessionUpdate);
				
				// 创建会话与客服关联数据
				Entity kfSessionServicerRelation = Entity.create("kf_session_servicer_relation");
				kfSessionServicerRelation.set("session_id", sessionId);
				kfSessionServicerRelation.set("userid", me.getLoginIdStr());
				kfSessionServicerRelation.set("start_time", DateUtil.now());
				kfSessionServicerRelation.set("status", 0); // 接待中
				if (KfSessionStatus.WAIT == kfSession.getInt("status")) {
					kfSessionServicerRelation.set("source", 0); // 首次接待
				} else if(KfSessionStatus.RESET == kfSession.getInt("status")){
					kfSessionServicerRelation.set("source", 1); // 重新激活
				}
				Db.insert(ds, kfSessionServicerRelation);

				// 给未接待人员推送隐藏会话的消息
				getWebSocket().sendMessage(Message.createMsg(Message.SESSION_DEL, kfSession), 
						getSessionUserid(ds, kfSession, me.getLoginIdStr()));
				
				// 如果是首次接待，则更新关联表相关接粉数量
				if (StrUtil.isBlank(kfSession.getStr("userid"))) {
					String sceneParam = kfSession.getStr("scene_param");
					
					Entity positionChannel = Db.createSqlParser("position_channel").where("state", sceneParam).findOne(ds);
					if (positionChannel != null) {
						String teamId = positionChannel.getStr("team_id");
						long timestamp = DateUtil.parse(kfSession.getStr("send_time")).getTime() / 1000;
						ExternalContactService.updateInCntByRel(ds, me.getLoginIdStr(), 3, teamId, timestamp + "");
						log.info("开始会话，更新关联表相关接粉数量，接粉组ID:{}", teamId);
					}
				}
			} catch (Exception e) {
				log.error("[KfSessionStartFunctionCall]开始会话时发生异常：{}", e.getMessage(), e);
			} finally {
				if (lock.isHeldByCurrentThread()) {
					lock.unlock();
				}
			}
		} else {
			log.info("[KfSessionStartFunctionCall]未获取到锁，忽略调用。main_id:{}", sessionId);
		}

		return JSONUtil.createObj();
	}
	
	/**
	 * 获取会话对应的非接待人员ID列表
	 * @param ds
	 * @param kfSession
	 * @param userid 当前接待人员ID
	 * @return
	 */
	private String[] getSessionUserid(DataSource ds, Entity kfSession, String userid) {
		String sceneParam = kfSession.getStr("scene_param");
		String sql = """
				select userid from fan_user_team_relation where team_id in(
				  select team_id from position_channel where state=? and sys_deleted=1
				) and sys_deleted=1 and status=0 and userid!=?
				""";
		DbList list = Db.query(ds, sql, sceneParam, userid);
		return list.stream().map(b -> b.getStr("userid")).toArray(String[]::new);
	}
    
    /**
     * 获取websocket对象
     * @return
     */
    private WebSocket getWebSocket() {
    	if (webSocket == null) {
    		webSocket = SpringUtil.getBean(WebSocket.class);
    	}
    	return webSocket;
    }
}
